package cn.sc.summer.gateway.task;

import cn.hutool.core.collection.CollUtil;
import cn.sc.summer.gateway.util.ThreadUtil;
import cn.sc.summer.constant.token.TokenConstant;
import cn.sc.summer.redis.util.RedisHelper;
import cn.sc.summer.token.encrypt.TokenUtil;
import cn.sc.summer.token.enums.LoginTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Set;
import java.util.concurrent.CompletableFuture;

/**
 * 类名：定时刷新无效token信息
 *
 * @author a-xin
 * @date 2023/10/24 15:10
 */
@Slf4j
@Component
public class RefreshTokenTask {

    @Resource
    private ThreadUtil threadUtil;

    /**
     * 定时任务，每15分钟刷新一次无效token
     */
    @Scheduled(cron = "0 0/15 * * * ?")
    public void refreshToken() {
        log.info("==> Starts detecting expired tokens......");

        CompletableFuture<Void> tokenFuture = CompletableFuture.runAsync(() -> {
            for (LoginTypeEnum enums : LoginTypeEnum.values()) {
                Set<String> webTokens = RedisHelper.getKeysByPrefix(enums.getSlogan());
                if (CollUtil.isNotEmpty(webTokens)) {
                    webTokens.parallelStream().forEach(key -> {
                        Object obj = new Object();
                        Set<ZSetOperations.TypedTuple<Object>> typedTuples = RedisHelper.zGetAllDES(key);
                        if (CollUtil.isNotEmpty(typedTuples)) {
                            synchronized (obj) {
                                typedTuples.parallelStream().forEach(token -> {
                                    if (!RedisHelper.hasKey(TokenConstant.ACCESS_TOKEN_PREFIX + token.getValue().toString())) {
                                        RedisHelper.zRemoveMember(key, token.getValue());
                                        log.warn("==> The token has expired and the token information has been deleted: {}", TokenUtil.analysisSimpleToken(token.getValue().toString()));
                                    }
                                });
                            }
                        }
                    });
                }
            }
        }, threadUtil.THREAD_POOL());

        CompletableFuture.allOf(tokenFuture).whenComplete((result, exception) -> {
            log.info("==> The token information is checked！");
        });
    }
}
